<?php
# ***** BEGIN LICENSE BLOCK *****
# This file is part of "myWiWall".
# Copyright (c) 2007-2008 CRP Henri Tudor and contributors.
# All rights reserved.
#
# "myWiWall" is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as published by
# the Free Software Foundation.
# 
# "myWiWall" is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with "myWiWall"; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# ***** END LICENSE BLOCK *****


/**
 * The Categories class allows you to access persistant data relevant to
 * the MyWiWall widget categories.
 * 
 * @author Laurent Haan <laurent.haan@gmail.com>
 * @author J�r�me Bogaerts <jerome.bogaerts@gmail.com>
 * @package mywiwall.models
 *
 */
class Categories
{
	/**
	 * Retrieve all widget categories in the database as json or raw format.
	 *
	 * @param string $format The format in which the categories data will be returned. It must be 'json' or 'raw' (data in array).
	 * @return The categories stored in the persistant database in the specified format.
	 */
	public static function retrieveCategories($format = 'json', $withEmpty = false)
	{
		// FIXME Rename the method retrieveCategories in retrieveAll
		$format = strtolower($format);
		if ($format != 'json' && $format != 'raw')
			throw new BadArgumentException(MwwException::MODEL, 
										   'The format parameter for Categories::retrieveCategories must be json or raw.');
			
		$db = DbUtil::accessFactory();
			
		// Statement execution.
		$rs = $db->select('SELECT C.id, C.category, COUNT(W.widgetId) AS widgetCount FROM categories C LEFT JOIN widgets W ON (W.category = C.id) GROUP BY C.id ORDER BY category ASC');

		$result = array();
				
		while($rs->fetch())
			$result[] = array('id' => $rs->id, 'category' => $rs->category, 'widgets' => $rs->widgetCount);
		
		// Here we create a fake category to represent an aggregation of widgets without any category.
		if ($withEmpty)
		{
			$fakeRs = $db->select('SELECT COUNT(widgetId) AS widgetCount FROM widgets WHERE category IS NULL');
			$fakeCategory = array('id' => null, 'category' => 'Widgets without category', 'widgets' => $fakeRs->widgetCount);
			$result[] = $fakeCategory;
		}
			
		switch ($format)
		{
			case 'json':
				return json_encode($result);
				break;
				
			case 'raw':
				return $result;
				break;
		}
	}
	
	/**
	 * Add a new Widget Category in the portal.
	 * 
	 * @param string $name The name of the new Widget Category.
	 */
	public static function add($name)
	{
		if (!strlen($name))
			throw new CategoryException(MwwException::MODEL,
										"The category name cannot be empty",
										null,
										CategoryException::EMPTY_NAME);
	
		// Database connexion retrieval and input data sanitizing.
		$db = DbUtil::accessFactory();
		$name = $db->escape($name);
		
		// Check if this category exists. If not, create the category.
		if (!self::exists($name))
		{
			if (!$db->execute("INSERT INTO categories VALUES('', '${name}')"))
				throw new DBException(MwwException::MODEL, 
									  "Unable to create the '${name}' category in the persistant database.");
		}
		else
		{
			// This category exists and we cannot create the requested category.
			throw new CategoryException(MwwException::MODEL,
										"The category '${name}' already exists.",
										null,
										CategoryException::ALREADY_EXISTS);
		}
	}
	
	/**
	 * Modify an existing Widget Category of the portal.
	 * 
	 * @param integer $id The numeric identifier of the category you need to change the name.
	 * @param string $newName The new name of the category you want to change the name.
	 */
	public static function modify($id, $newName)
	{
		if (!strlen($newName))
			throw new CategoryException(MwwException::MODEL,
										"The category name cannot be empty",
										null,
										CategoryException::EMPTY_NAME);
	
		$db = DbUtil::accessFactory();
		$id = $db->escape($id);
		$newName  = $db->escape($newName);
		
		// If the newName is the same than the old name, we just return.
		$rs = $db->select("SELECT LOWER(category) AS 'oldname' FROM categories WHERE id = ${id}");
		
		if ($rs->count() > 0 && $rs->oldname == strtolower($newName))
			return;
		
		if (!self::exists($newName))
		{
			// We can modify the category name.
			if (!$db->execute("UPDATE categories SET category = '${newName}' WHERE id = ${id}"))
				throw new DBException(MwwException::MODEL,
									  "Unable to create the '${newName}' category in the persistant database.");
		}
		else
		{
			// The new category name represents an existing category.
			throw new CategoryException(MwwException::MODEL,
										"The category '${newName}' already exists.",
										null,
										CategoryException::ALREADY_EXISTS);
		}
	}
	
	/**
	 * Delete an existing Widget Category of the portal.
	 * 
	 * @param integer $id The numeric identifier of the Widget Category you want to delete.
	 */
	public static function delete($id)
	{
		$db = DbUtil::accessFactory();
		$id = $db->escape($id);
		
		if (!$db->execute("DELETE FROM categories WHERE id = ${id}"))
			throw new DBException(MwwException::MODEL,
								  "Unable to delete the category with id '${id}'");
	}
	
	/**
	 * Verifies if a Widget Category with a given name exists in the
	 * persistent database of the portal.
	 * 
	 * @param string $name The name of the Widget Category you want to verify the existence.
	 */
	public static function exists($name)
	{
		$db = DbUtil::accessFactory();
		$name = $db->escape($name);
		$toLowerName = strtolower($name);
		
		// Check if this category exists.
		$rs = $db->select("SELECT COUNT(*) AS 'catcount' FROM categories WHERE LOWER(category) = '${toLowerName}'");
		
		return $rs->catcount;
	}
}
?>